package com.irdstudio.efp.flow.ext.impl;

import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.irdstudio.efp.console.service.facade.SUserDutyService;
import com.irdstudio.efp.console.service.facade.SUserRoleService;
import com.irdstudio.efp.console.service.vo.SUserOrgByDutyIdVO;
import com.irdstudio.efp.flow.common.constance.FlowConstance;
import com.irdstudio.efp.flow.common.vo.AprvUserVO;
import com.irdstudio.efp.flow.common.vo.EngineVO;
import com.irdstudio.efp.flow.common.vo.PageApproveVO;
import com.irdstudio.efp.flow.ext.AprvUserCalc;
import com.irdstudio.efp.flow.service.facade.BizFlowProcessService;
import com.irdstudio.efp.flow.service.facade.InstFlowEventService;
import com.irdstudio.efp.flow.service.facade.InstFlowProcessService;
import com.irdstudio.efp.flow.service.vo.BizFlowProcessVO;
import com.irdstudio.efp.flow.service.vo.InstFlowEventVO;
import com.irdstudio.basic.framework.core.cache.CacheManager;
import com.irdstudio.basic.framework.core.constant.CacheConstant;
import com.irdstudio.basic.framework.core.exception.FlowException;
import com.irdstudio.basic.framework.core.vo.OrgInfoCacheVO;

/**
 * 
 * 节点处理人信息计算实现类
 * 
 * @author Cytus_
 * @since 2018年5月11日 下午7:58:37
 * @version 1.0
 *
 */
@Service("aprvUserCalc")
public class AprvUserCalcImpl implements AprvUserCalc {

	private static Logger logger = LoggerFactory.getLogger(AprvUserCalcImpl.class);
	
	@Autowired
	@Qualifier("instFlowProcessService")
	private InstFlowProcessService instFlowProcessService;
	
	@Autowired
	@Qualifier("sUserDutyService")
	private SUserDutyService sUserDutyService;
	
	@Autowired
	@Qualifier("bizFlowProcessService")
	private BizFlowProcessService bizFlowProcessService;
	
	@Autowired
	@Qualifier("instFlowEventService")
	private InstFlowEventService instFlowEventService;
	
	@Autowired
	@Qualifier("sUserRoleService")
	private SUserRoleService sUserRoleService;
	
	
	public AprvUserVO aprvUserCalc(EngineVO evo) throws FlowException {
		
		logger.info("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +"计算当前处理人员信息开始......");
		
		//先获得当前节点配置的处理岗位信息
		BizFlowProcessVO bizFlowProcessQuery = new BizFlowProcessVO();
		bizFlowProcessQuery.setBizNodeId(evo.getNodeId());
		bizFlowProcessQuery.setBizEventId(evo.getEventId());
		BizFlowProcessVO bizFlowProcessVO = bizFlowProcessService.queryFirstByEventAndNodeId(bizFlowProcessQuery);
		if (Objects.isNull(bizFlowProcessVO)) {
			logger.error("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +"查询处理人员信息为空!");
			throw new FlowException("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +"查询处理人员信息为空!");
		}
		SUserOrgByDutyIdVO vo = null;
		InstFlowEventVO eventVo = instFlowEventService.queryByBizSerno(evo.getBizSerno());
		
		/**
		 * 
		 * Start modify by Cytus_ at 2018-06-19 15:40:23 行方要求流程不进行自动分配审批人员信息，由各自任务认领形式实现，后期如果实现调单功能且行方要求放开自动分配，则可放开以下注释
		 * 
		 */
		/*String dutyCode = bizFlowProcessVO.getBizNodeDutyNo();
		
		
		//查询满足该岗位的用户相关信息
		logger.info("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +"查询到当前节点配置的审批岗位编号为:"+ dutyCode +", 业务所属机构信息为："+ eventVo.getBizLegalOrgCode());
		List<SUserOrgByDutyIdVO> listUsers = null;
		try {
			listUsers = sUserDutyService.queryOrgUserByDutyIdOrgId(dutyCode, eventVo.getBizLegalOrgCode());
		} catch (Exception e) {
			logger.warn("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +", 岗位:"+ dutyCode +"查询当前机构满足条件的人员信息出现异常!");
			//throw new FlowException("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +", 岗位:"+ dutyCode +"查询满足条件的人员信息出现异常!");
		}
		
		if (Objects.isNull(listUsers) || listUsers.isEmpty()) {
			logger.error("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +", 业务所属机构："+ eventVo.getBizLegalOrgCode() +"未查到岗位编号为："+ dutyCode +"的审批人员信息, 即将查询其所属法人机构信息!");
			try {
	            listUsers = sUserDutyService.queryLegalUserByDutyIdLeagalId(dutyCode, eventVo.getBizLegalOrgCode());
	        } catch (Exception e) {
	            logger.error("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +", 岗位:"+ dutyCode +"查询当前机构所属法人机构满足条件的人员信息出现异常!");
	            //throw new FlowException("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +", 岗位:"+ dutyCode +"查询满足条件的人员信息出现异常!");
	        }
			//throw new FlowException("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +"未查询到处理人员信息!");
		}
		
		//查询不满足条件的处理人员信息
		List<String> allocatList = instFlowProcessService.queryDissatisfyAprvMaxUsers(
				new FlowAprvUserInqVO(evo.getEventId(), evo.getNodeId(), bizFlowProcessVO.getMaxAprvNum(), 
						Arrays.asList(FlowConstance.NODE_STATUS_EXCEPTION, FlowConstance.NODE_STATUS_PAUSE)));
		
		List<SUserOrgByDutyIdVO> satisfyUser = null;
		if (Objects.nonNull(listUsers) && !listUsers.isEmpty()) {
		    if (Objects.nonNull(allocatList) && !allocatList.isEmpty()) {
		        satisfyUser = listUsers.parallelStream().filter(s -> !allocatList.contains(s.getUserCode())).collect(Collectors.toList());
		    } else {
		        satisfyUser = listUsers;
		    }
		    if (Objects.nonNull(satisfyUser) && !satisfyUser.isEmpty()) {
		        vo = satisfyUser.get(ThreadLocalRandom.current().nextInt(0, satisfyUser.size()));
		    }
		}*/
		
		
		//随机获得处理人员信息
		/*if (Objects.isNull(allocatList) || allocatList.isEmpty()) { //不存在不满足条件的处理人员
			int location = ThreadLocalRandom.current().nextInt(0, listUsers.size());
			vo = listUsers.get(location);
		} else {	//存在不满足的处理人员，先进行不满足的人员信息剔除，在随机获得
			List<SUserOrgByDutyIdVO> satisfyUser = listUsers.parallelStream().filter(s -> !allocatList.contains(s.getUserCode())).collect(Collectors.toList());
			int location = ThreadLocalRandom.current().nextInt(0, satisfyUser.size());
			vo = listUsers.get(location);
		}*/
		/**
		 * 
		 * End modify by Cytus_ at 2018-06-19 15:40:23
		 * 
		 */
		
		if (Objects.isNull(vo)) {
			logger.warn("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +"未找到处理人员信息, 执行默认处理人员信息开始.....");
			vo = new SUserOrgByDutyIdVO();
			vo.setOrgCode(eventVo.getBizLegalOrgCode());
			try {
                OrgInfoCacheVO cacheVo = CacheManager.getCacheObject(CacheConstant.CACHE_KEY_ORG_INFOS, eventVo.getBizLegalOrgCode());
                vo.setOrgName(cacheVo.getOrgName());
                vo.setLegalOrgCode(cacheVo.getLegalOrgCode());
            } catch (Exception e) {
                logger.error("查询机构："+ eventVo.getBizLegalOrgCode() +"的缓存机构信息出现异常! cause by:"+ e.getMessage());
            }
			vo.setUserCode(FlowConstance.TASK_POOL_USER_ID);
			vo.setUserName(FlowConstance.TASK_POOL_USER_NAME);
			/*List<SUserVO> userVos = sUserRoleService.queryAdminbyLegalOrg(eventVo.getBizLegalOrgCode());
			if (Objects.nonNull(userVos) && !userVos.isEmpty()) {
			    int location = ThreadLocalRandom.current().nextInt(0, userVos.size());
			    SUserVO userVo = userVos.get(location);
			    vo = new SUserOrgByDutyIdVO();
			    vo.setLegalOrgCode(userVo.getLegalOrgCode());
			    vo.setUserCode(userVo.getUserCode());
			    vo.setUserName(userVo.getUserName());
			    vo.setOrgCode(userVo.getOrgCode());
			    vo.setOrgName(userVo.getOrgName());
			} else {
			    logger.error("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +", 业务所属法人机构:"
                        + eventVo.getBizLegalOrgCode() +"未查询到法人机构默认处理人员信息!");
			    throw new FlowException("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +", 业务所属法人机构:"
			            + eventVo.getBizLegalOrgCode() +"未查询到法人机构默认处理人员信息!");
			}*/
		}
		
		AprvUserVO userVo = new AprvUserVO();
		userVo.setOrgId(vo.getOrgCode());
		userVo.setOrgName(vo.getOrgName());
		userVo.setUserId(vo.getUserCode());
		userVo.setUserName(vo.getUserName());
		userVo.setLegalOrgId(vo.getLegalOrgCode());
		logger.info("节点ID："+ evo.getEventId() +", 实例化节点ID："+ evo.getNodeId() +"计算当前处理人员信息结束, 查询到的待执行人员信息为:"+ userVo.toString());
		setAprvInfo(userVo, evo);
		return userVo;
	}
	
	/*private InstFlowEventVO getInstFlowEventByNodeIdAndEventId(String eventId, String instanceNodeId) {
		InstFlowEventVO queryInfo = new InstFlowEventVO();
		queryInfo.setBizEventId(eventId);
		queryInfo.setInstNodeId(instanceNodeId);
		return instFlowEventService.queryByNodeIdAndEventId(queryInfo);
	}*/
	
	private void setAprvInfo(AprvUserVO userVo, EngineVO evo) {
		PageApproveVO vo = new PageApproveVO();
		vo.setAprvOrgCode(userVo.getOrgId());
		vo.setAprvUserId(userVo.getUserId());
		vo.setAprvUserName(userVo.getUserName());
		evo.getPluginVo().addVOs(FlowConstance.APRV_USER_KEY, vo);
	}

}
